/*
** TowBowlTactics, an adaptation of the tabletop game Blood Bowl.
** 
** Copyright (C) 2006, 2007 The TBT Team.
** 
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
** 
** The complete GNU General Public Licence Notice can be found as the
** `NOTICE' file in the root directory.
** 
** The TBT Team consists of people listed in the `AUTHORS' file.
*/

#include "CRules.hh"
#include "CPlayerMsg.hh"
#include "CTeam.hh"

CTeam::CTeam(int team_id, CRules* r, CPlayerMsg* pm)
  : Team<CPlayer>(team_id),
    r_(r),
    pm_(pm)
{
}

CTeam::~CTeam()
{
}

// Parse our xml team file, send this to server, and wait that
// it return it to us to fill our data structure.
void CTeam::loadConfig(const std::string& team_file)
{
  xml_team_.parse(team_file);
  xml_team_.switchToTeamGlobals();

  MsgTeamInfo pkt;
  pkt.reroll = xml_team_.getData<int>("reroll");
  stringToPacket(pkt.team_name, xml_team_.getData<std::string>("name"), 32);
  stringToPacket(pkt.nation_name, xml_team_.getAttr<std::string>("team", "race"), 32);
  stringToPacket(pkt.coach_name, xml_team_.getData<std::string>("coach"), 32);
  r_->sendPacket(pkt);

  xml_formation_.parse(xml_team_.getData<std::string>("formation"));
  for (int i = 0; i < MAX_PLAYER; i++)
    {
      if (!xml_team_.switchToPlayer(i + 1))
        break;
      loadPlayerConfig(xml_team_, i);
    }
}

// Load player info from xml.
// A player will be created when message will be returned by server.
void CTeam::loadPlayerConfig(xml::XMLTeam& xml_team, int player_id)
{
  xml_team.switchToPlayer(player_id + 1);

  MsgPlayerCreate pkt;
  pkt.player_id = player_id;
  stringToPacket(pkt.name, xml_team.getAttr<std::string>("player", "name"), 32);
  pkt.ma = xml_team.getData<int>("ma");
  pkt.st = xml_team.getData<int>("st");
  pkt.ag = xml_team.getData<int>("ag");
  pkt.av = xml_team.getData<int>("av");

  pkt.skill_nb = 0;
  try {
    for (int i = 0; pkt.skill_nb < MAX_SKILL; i++)
      {
        std::string skill = xml_team.getData<std::string>("skill", i);

        if (skill == "Block")
          pkt.skill[pkt.skill_nb] = SK_BLOCK;
        else if (skill == "Catch")
          pkt.skill[pkt.skill_nb] = SK_CATCH;
        else if (skill == "Dodge")
          pkt.skill[pkt.skill_nb] = SK_DODGE;
        else if (skill == "Pass")
          pkt.skill[pkt.skill_nb] = SK_PASS;
        else if (skill == "Surehand")
          pkt.skill[pkt.skill_nb] = SK_SUREHANDS;
        else
          pkt.skill[pkt.skill_nb] = SK_UNASSIGNED;

        if (pkt.skill[pkt.skill_nb] != SK_UNASSIGNED)
          pkt.skill_nb++;
      }
  }  catch (xml::XMLError&) {}

  pkt.player_position = xml_team.getData<int>("positionid");
  stringToPacket(pkt.player_img, xml_team.getAttr<std::string>("player", "display"), 32);
  stringToPacket(pkt.position_name, xml_team.getAttr<std::string>("player", "position"), 32);
  
  r_->sendPacket(pkt);
}

// Send the content of formation.xml to the server. On half inits.
void CTeam::placeTeam(int formation_id)
{
  xml_formation_.switchFormationId(formation_id);
  for (int i = 0; i < MAX_PLAYER; i++)
    if (player_[i] != NULL
        && (player_[i]->getStatus() == STA_RESERVE
          || player_[i]->getStatus() == STA_STANDING))
      {
        MsgPlayerPos pkt;
        Position pos = xml_formation_.getPos(player_[i]->getId() + 1);
        pkt.player_id = player_[i]->getId();
        pkt.row = pos.row;
        pkt.col = pos.col;
        // if this is team 2, mirror on rows [|13-25|].
        if (team_id_ == 1)
          pkt.row = ROWS - pkt.row - 1;
        r_->sendPacket(pkt);
      }
}

int CTeam::declareAction(CPlayer* p, enum eDeclaredAction action)
{
  if (blitz_done_ && action == DCL_BLITZ)
    {
      LOG2("You have halready done a blitz action this turn.");
      return INVALID_ACTION;
    }
  if (pass_done_ && action == DCL_PASS)
    {
      LOG2("You have halready done a pass action this turn.");
      return INVALID_ACTION;
    }
  return p->declareAction(action);
}

void CTeam::msgTeamInfo(const MsgTeamInfo* m)
{
  team_name_ = packetToString(m->team_name);
  nation_name_ = packetToString(m->nation_name);
  coach_name_ = packetToString(m->coach_name);
  reroll_ = m->reroll;
}

void CTeam::msgPlayerCreate(const MsgPlayerCreate* m)
{
  player_[m->player_id] = new CPlayer(r_, m);
  pm_->setPlayer(m->client_id, m->player_id, player_[m->player_id]);
  r_->onEvent(m);
}

void CTeam::msgReroll(const MsgReroll* m)
{
  if (r_->getState() == GS_REROLL)
    r_->restoreGameState();
  if (m->reroll)
    {
      reroll_used_ = true;
      reroll_remain_ = reroll_remain_ - 1;
    }
  r_->onEvent(m);
}

void CTeam::msgTouchdooown(const MsgTouchdooown* m)
{
  incrementScore();
  r_->onEvent(m);
}
